<?php
/**
 *
 * Created by PhpStorm.
 * User: Egor <http://gitee.com/seosite>
 * Date: 2018/6/25
 * Time: 下午3:19
 * Updatetime:
 * updater：
 */

namespace Wap\Controller;

use Think\Exception;

class ElasticSearchController extends BaseController
{
    private $elasticsearch;
    private $dbName;
    private $tbName;


    public function __construct()
    {
        $this->dbName = 'finance';
        $this->tbName = 'think_';

        Vendor('Elasticsearch.autoload');
        try{
            $params['hosts'] = array(
                '127.0.0.1:9200'
            );
            $this->elasticsearch = new \Elasticsearch\Client($params);
        }catch (Exception $e){
            $r = $e->getMessage();
            echo json_encode($r);
        }
    }

    /**
     * @desc 初始化params参数
     * @author Egor<http://gitee.com/seosite>
     * @return array
     */
    public function initParams($dbName = '',$tbName = '')
    {
        return [
            'index' => empty($dbName)?$this->dbName:$dbName,
            'type'  => empty($tbName)?$this->tbName:$tbName,
        ];
    }


    /**
     * @desc 创建索引
     * 在设置mapping之前需要创建索引
     * @author Egor<http://gitee.com/seosite>
     * @param $dbName
     */
    public function createIndex($dbName = '')
    {
        try{
            $indexParams = [
                'index' => empty($dbName)?$this->dbName:$dbName,
            ];
            $r = $this->elasticsearch->indices()->create($indexParams);
        }catch (Exception $e){
            $r = $e->getMessage();
        }
        echo json_encode($r);
    }


    /**
     * @desc 删除索引
     * @author Egor<http://gitee.com/seosite>
     * @param $dbName
     */
    public function deleteIndex($dbName = '')
    {
        try{
            $indexParams = [
                'index' => empty($dbName)?$this->dbName:$dbName,
            ];
            $r = $this->elasticsearch->indices()->delete($indexParams);
        }catch (Exception $e){
            $r = $e->getMessage();
        }

        echo json_encode($r);
    }


    /**
     * @desc 设置全文索引mapping
     * @author Egor<http://gitee.com/seosite>
     * @param $data
     */
    public function setMapping($data,$dbName='',$tbName='')
    {
        try{
            $indexParam = $this->initParams($dbName,$tbName);

            $mapParam = [];

            foreach ($data as $field => $field_type){
                $mapParam[$field] = [
                    'type'  =>  $field_type,
                ];

            }

            $indexParam['body'][$indexParam['type']]['properties'] = $mapParam;

            $r = $this->elasticsearch->indices()->putMapping($indexParam);

        }   catch (Exception $e){
            $r = $e->getMessage();
        }
        echo  json_encode($r);
    }


    /**
     * @desc 添加索引
     * @author Egor<http://gitee.com/seosite>
     * @param $data
     */
    public function add($data,$dbName='',$tbName='')
    {
        try{
            $params = $this->initParams($dbName,$tbName);

            if (array_key_exists('work_id',$data)){
                $params['id'] = $data['work_id'];
            }

            $params['body'] = $data;

            $r = $this->elasticsearch->index($params);

        }catch (Exception $e){
            $r = $e->getMessage();
        }

        echo json_encode($r);
    }


    /**
     * @desc 搜索，测试使用
     * @author Egor<http://gitee.com/seosite>
     * @param $data
     */
    public function query($data,$tbName)
    {
        try{
            $tbName = empty($tbName)?'video,direct,audio,mp3,report,picture,news,data,meeting,columnist,qa,question':$tbName;
            $params = $this->initParams('finance',$tbName);

            $field = key($data);

            $query = [

                'match' =>  [
                    $field  =>  [
                        'query' =>  $data[$field],
                        'minimum_should_match' =>  '90%',
                    ]
                ]
            ];

            $highlight = [
                'fields'    =>  [
                    $field  =>  [
                        'pre_tags'  =>  '<strong>',
                        'post_tags'  =>  '</strong>',
                    ]
                ]
            ];

            $param['body']['query'] = $query;
            $param['body']['highlight'] = $highlight;

            $r = $this->elasticsearch->search($params);

        }catch (Exception $e){

            $r = $e->getMessage();

        }

        echo json_encode($r);

    }

    /**
     * @desc del index
     * @author Egor<http://gitee.com/seosite>
     * @param $index|dbName
     */
    public function delIndex($index)
    {
        $deleteParams['index'] = $index;

        $this->elasticsearch->indices()->delete($deleteParams);

    }

    /**
     * @desc 删除文档
     * @author Egor<http://gitee.com/seosite>
     * @param $data:['index':'finance','type':'direct','id':'direct_1']
     */
    public function delDocument($data)
    {
        try{
            $r = $this->elasticsearch->delete($data);
        }catch (Exception $e){
            $r = $e->getMessage();
        }

        echo json_encode($r);
    }

    /**
     * @desc 删除文档
     * @author Egor<http://gitee.com/seosite>
     * @param $data ['index':'finance','type':'direct','id':'direct_1']
     */
    public function afterDel($data)
    {
        try{
            if (count(explode(',',$data['id']))>1){
                $a = $this->elasticsearch;
                foreach (explode(',',$data['id']) as $k=>$v){
                    $data['id'] = $v;
                    $r = $a->delete($v);
                }
            }else{
                $this->elasticsearch->delete($data);
            }
        }catch (Exception $e){
            $r = $e->getMessage();
        }

//        echo json_encode($r);
    }


    /**
     * @desc 添加
     * @author Egor<http://gitee.com/seosite>
     * @param $data
     */
    public function afterAdd($data,$dbName = '',$tbName = '')
    {
        try{
            $params = $this->initParams($dbName,$tbName);

            if (array_key_exists('id',$data)){
                $params['id'] = $data['id'];
            }

            $params['body'] = $data;
            $r = $this->elasticsearch->index($params);

        }catch (Exception $e){
            $r = $e->getMessage();
        }

//        echo json_encode($r);
    }


    /**
     * @desc 搜索单一
     * @author Egor<http://gitee.com/seosite>
     * @param $data
     * @param $tbName
     * @param $from
     * @param $size
     * @param $sortName
     * @param $sortType
     * @return array
     */
    public function searchOne($data,$from,$size,$sortName,$sortType)
    {
        try{
            $params = $this->initParams();

            $params['from'] = $from;
            $params['size'] = $size;

            $field = key($data);

            $query = [

                'match' =>  [
                    $field  =>  [
                        'query' =>  $data[$field],
                        'minimum_should_match' =>  '90%',
                    ]
                ]
            ];

            $highlight = [
                'fields'    =>  [
                    $field  =>  [
                        'pre_tags'  =>  '{',
                        'post_tags'  =>  '}',
                    ]
                ]
            ];

            $sort = [
                $sortName   =>  ['order'=>$sortType]
            ];

            $params['body']['query'] = $query;
            $params['body']['highlight'] = $highlight;

            $r = $this->elasticsearch->search($params);

            echo json_encode($r);

            return showErrorMsg(L('_OPERATION_SUCCESS_'),0,2,$r['hits']['hits']);

        }catch (Exception $e){

            $r = $e->getMessage();

            return showErrorMsg($r,100002);
        }
    }


    /**
     * @desc 复合查询，给定一个关键字，和指定的字段进行查询，结果高亮显示，测试使用
     * @author Egor<http://gitee.com/seosite>
     * @param $data ['keyword'=>'你好','fields'=>'title,uname']
     * @param $tbName
     */
    public function multiSearch($data,$tbName)
    {
        try{
            $tbName = empty($tbName)?'video,direct,audio,mp3,report,picture,news,data,meeting,columnist,qa,question':$tbName;
            $searchParams = $this->initParams();

            $searchParams['index'] = 'finance';
            $searchParams['type'] = $tbName;
            $searchParams['from'] = 0;
            $searchParams['size'] = 100;

            $query = [
                'multi_match' =>  [
                    'query' =>  $data['keyword'],
                    'type' =>  'most_fields',
                    'fields' =>  explode(',',$data['fields']),
                ]
            ];


            $highlight = array();
            foreach (explode(',',$data['fields']) as $k=>$v){
                $highlight['fields'][$v] = [
                    'pre_tags'  =>  '{',
                    'post_tags'  =>  '}',
                ];
            }


            $searchParams['body']['query'] = $query;
            $searchParams['body']['highlight'] = $highlight;

            $r = $this->elasticsearch->search($searchParams);

        }catch (Exception $e){

            $r = $e->getMessage();

        }

        echo json_encode($r);
    }

    /**
     * @desc 精确搜索，统一使用这个
     * @author Egor<http://gitee.com/seosite>
     * @param $data
     * @param $from
     * @param $size
     * @param $sortName
     * @param $sortType
     */
    public function filterSearch($data,$from,$size,$sortName,$sortType)
    {
        try{
            $searchParams = $this->initParams();

            $searchParams['body']['from'] = $from;
            $searchParams['body']['size'] = $size;
            $searchParams['body']['version'] = true;
            $searchParams['body']['sort'][] = [$sortName   =>  ['order'=>$sortType]];


            $query = [];
            $query_temp = [];
            $highlight_temp = array();
            foreach ($data as $k=>$v){
                $highlight_temp = array($k=>["pre_tags"=>"{","post_tags"=>"}"]);
                if ($k=='uid'){
                    $query_temp = [
                        'must'=>[
                            ['match'=>[$k=>$v]]
                        ]
                    ];
                }else{
                    $query_temp = [
                        'should'=>[
                            ['match'=>[$k=>$v]]
                        ]
                    ];
                }
            }
            $highlight = [
                'number_of_fragments'   =>  3,
                'fragment_size'         =>  150,
                'fields'                =>  $highlight_temp
            ];


            $query['bool'] = $query_temp;
            $searchParams['body']['query'] = $query;
            $searchParams['body']['highlight'] = $highlight;
            $r = $this->elasticsearch->search($searchParams);

            return showErrorMsg(L('_OPERATION_SUCCESS_'),0,2,$r['hits']['hits']);


        }catch (Exception $e){

            $r = $e->getMessage();

            return showErrorMsg($r,100002);
        }
    }

    public function afterSearch($data,$tbName)
    {
        try{
            $tbName = empty($tbName)?'video,direct,audio,mp3,report,picture,news,data,meeting,columnist,qa,question':$tbName;
            $params = $this->initParams('finance',$tbName);

            if (!is_array($data)){
//            $data = object2array(json_decode($data));
            }

            $searchParams['index'] = 'finance';
            $searchParams['type'] = $tbName;
            $searchParams['from'] = 0;
            $searchParams['size'] = 100;
//            $searchParams['sort'] = array(
//                '_score' => array(
//                    'order' => 'desc'
//                )
//            );

            $field = key($data);

            var_dump($field);

            foreach ($data as $k=>$v){
                $query = [

                    'match' =>  [
                        $field  =>  [
                            'query' =>  $data[$field],
                            'minimum_should_match' =>  '90%',
                        ]
                    ]
                ];
            }
            $query = [

                'match' =>  [
                    $field  =>  [
                        'query' =>  $data[$field],
                        'minimum_should_match' =>  '90%',
                    ]
                ]
            ];
//
            $highlight = [
                'fields'    =>  [
                    $field  =>  [
                        'pre_tags'  =>  '{',
                        'post_tags'  =>  '}',
                    ]
                ]
            ];
//
            $searchParams['body']['query'] = $query;
            $searchParams['body']['highlight'] = $highlight;

            $r = $this->elasticsearch->search($searchParams);

        }catch (Exception $e){

            $r = $e->getMessage();

        }

        echo json_encode($r);
    }


    /**
     * @desc 初始化项目第一步
     * @author Egor<http://gitee.com/seosite>
     */
    public function initProject()
    {
        //1.create index
        $this->createIndex('finance');

        //2.setting mapping
        $data_mapping = [
            'work_id'       => 'text',
            'id'            => 'long',
            'title'         => 'text',
            'message'       => 'text',
            'type'          => 'text',
            'views'         => 'long',
            'uid'           => 'long',
            'create_time'   => 'long',
            'created'       => 'date',
            'uname'         => 'text',
        ];

        $this->setMapping($data_mapping);
        die('开整吧，兄弟');
    }

    /**
     * @desc 初始化第二步
     * @author Egor<http://gitee.com/seosite>
     */
    public function secondInit()
    {
        //3.add data|第一次安装，不需要这一步

        $videoList = M('qa')->where(['is_draft'=>2,'is_show'=>1])->select();

        foreach ($videoList as $k=>$v){
            $add_data = [
                'work_id' => 'qa_'.$v['id'],
                'id' => $v['id'],
                'title' => $v['content'],
                'message' => '',
                'type' => 'video',
                'views' => $v['views'],
                'uid' => $v['uid'],
                'create_time' => $v['create_time'],
                'created' => date('Y-m-d',$v['create_time']),
                'uname' => ''
            ];
            $this->add($add_data);
        }
    }
}